using namespace std;

bool relation_name(string name);//
 bool expr(vector<string> line1);
 bool atomic_expr(vector<string> line);
 bool selection(vector<string>line);
 bool conjunction(vector<string> line, int count);
 bool operand(string line);
 bool op(string line);
bool literal(string line);
bool projection(vector<string> line);
bool attribute_list(vector<string> line, int count);
bool renaming(vector<string> line);
bool product(vector<string> line);


void Q(){
	//cout << "QUERY" << endl;
}
void RN(){
	//cout << "\tRELATION NAME" << endl;
}
void ID(){
	//cout << "\t\tIDENTIFIER" << endl;
}
void EX(){
	//cout << "\t\t\tEXPRESSION" << endl;
}
void ATM(){
	//cout << "\t\t\t\tATOMIC EXPRESSION" << endl;
}
void SEL(){
	//cout << "\t\t\t\tSELECT" << endl;
}
void PRO(){
	//cout << "\t\t\t\tPROJECTION" << endl;
}
void REN(){
	//cout << "\t\t\t\tRENAMING" << endl;
}
void UNI(){
	//cout << "\t\t\t\tUNION" << endl;
}
void DIF(){
	//cout << "\t\t\t\tDIFFERENCE" << endl;
}
void PROD(){
	//cout << "\t\t\t\tPRODUCT" << endl;
}
void CON(){
	//cout << "\t\t\t\t\tCONJUNCTION" << endl;
}

bool query(vector<string> line) // line is a vector of strings where each ellement is a word in the command line
{    
    if (relation_name(line[0]))// relation name
    { 
		if(line[1]=="<-")
		{       
			if(expr(line))//expr
            {
				Q();
                return true;
            }
			else
			{
				cout<<"bad expr";
			}
        }
		else
		{
			cout<<"bad <-";
		}
    }
	return false;
}

bool relation_name(string name)
{   
	int i=0;
	for( i=0; i<name.size(); i++)
	{
		if (!(isalpha(name[i]) || isdigit(name[i]) || name[i]=='_'))
        {
            return false;
        }
		i++;
	}
	RN();
    return true;
}

 bool expr(vector<string> line )//IT THROWS AWAY THE FIRST TWO ELLEMENTS IN THE VECTOR
 {
	int i=2;
	vector<string> line1;
	while(i<line.size())
	{
		line1.push_back(line[i]);
		i++;
	}	
	if(atomic_expr(line1)||selection(line1)|| projection(line1)|| renaming(line1)/*||union(line1)||difference(line1) optional)*/||product(line1))
	{
		EX();
		return true;
	}
	else
	{
		return false;
	}
}

bool atomic_expr(vector<string> line)
{
	if(line[0]=="(")
	{
		if(line.back() !=")")
		{
			//error 
		}
		else
		{
			line.insert(line.begin(),"#");
			line.erase(line.end()-1);
			if(expr(line))
			{
				ATM();
				return true;
			}
			else
			{
			// error statement
			}
		}
	}
	if(relation_name(line[0])&&(line.size()==1))
	{
		ATM();
		return true;
	}
	return false;
}

bool selection(vector<string> line)
{
	if(line[0]=="select"|| line[0] == "SELECT")
	{ 
		if(line[1]=="(")
		{ 
			line.erase(line.begin(), line.begin()+2); // deletes the first two ellements in the copy of line passed to select.
			int i=0, count=0;
			while(i<line.size())
			{
				if(line[i]==")")
				{
					count=i;
					break;
				}
				i++;
			}
			if(count==0)
			{
			 cout<<"error count=0";
			}
			else
			{ 
				if(conjunction(line,count-1))
				{ 
					line.erase(line.begin(),line.begin()+count+1);
					if(atomic_expr(line))
					{
						SEL();
						return true;
					}
					else
					{
						//error atomic expr expected after condition
					}
				}
				else
				{
					// incorrect condition
				}
			}
		}
		else
		{
			//missing paranthesis
		}
	}
	return false;
}

bool conjunction(vector<string> line, int count)
{
	int i=0,check=0;
	if(!(i+2<=count))
	{
	check=1;
	}
		while((check==0)&&(i+2<=count))
		{
			check=1;
			if(operand(line[i]))
			{
				if(op(line[++i]))
				{
					if(operand(line[++i]))
					{
						check=0;
						if(i<count)
						{
							if(line[i]=="&&")
							{
								i++;
							}
						}
		
					}
					else
					{
						//opperand missing
					}
				}
				else
				{
					//operation missing
				}
			}
			else
			{
				//error invalid opperand
			}
			if(check==1)
			{
				return false;
			}
		}
		if(check==1)
			{
				return false;
			}
		CON();
		return true;
	}
	
bool operand(string line)
{ 
	if((line[0] == '\"')&&(line[line.size()-1] == '\"'))
	{
		line.erase(line.begin());
		line.erase(line.end()-1);
	}
	
	if(relation_name(line)||literal(line))
	{
		return true;
	}
	return false;
}
bool op(string line)
{
	if(line == "=="||"!= "|| "<" ||">"||"<="||">=")
	{
		return true;
	}
	return false;
}

bool literal(string name)
{   
	int i=0;
/*  if(name[0]==NULL)
    {       
        return false;
    }
*/	
	for(i=0; i<name.size(); i++)
	{
		if (!(isalpha(name[i])||isdigit(name[i])))
        {
            return false;
        }
		i++;
	}
    return true;
}

bool projection(vector<string> line)
{
	if(line[0]=="project"||"PROJECT")
	{
		if(line[1]=="(")
		{
			line.erase(line.begin(), line.begin()+2); // deletes the first two ellements in the copy of line passed to select.
			int i=0, count=0;
			while(i<line.size())
			{
				if(line[i]==")")
				{
					count=i;
					break;
				}
				i++;
			}
			if(count==0)
			{
			// error no attribute names
			}
			else
			{
				if(attribute_list(line,count-1))
				{
					line.erase(line.begin(),line.begin()+count+1);
					if(atomic_expr(line))
					{
						PRO();
						return true;
					}
					else
					{
						//error atomic expr expected after condition
					}
				}
				else
				{
					// incorrect attribute names
				}
			}
		}
		else
		{
			//missing paranthesis
		}
	}
	return false;
}

bool attribute_list(vector<string> line, int count)
{
	int i=0;
	while(i<=count)
	{
		if(!relation_name(line[i]))// atribute nme==relation name
		{
			return false;
		}
		i++;
	}
	return true;
}

bool renaming(vector<string> line)
{
	if(line[0]=="rename"||"RENAME")
	{
		if(line[1]=="(")
		{
			line.erase(line.begin(), line.begin()+2); // deletes the first two ellements in the copy of line passed to select.
			int i=0, count=0;
			while(i<line.size())
			{
				if(line[i]==")")
				{
					count=i;
					break;
				}
				i++;
			}
			if(count==0)
			{
			// error no attribute names
			}
			else
			{
				if(attribute_list(line,count-1))
				{
					line.erase(line.begin(),line.begin()+count+1);
					if(atomic_expr(line))
					{
						REN();
						return true;
					}
					else
					{
						//error atomic expr expected after condition
					}
				}
				else
				{
					// incorrect attribute names
				}
			}
		}
		else
		{
			//missing paranthesis
		}
	}
	return false;
}

bool product(vector<string> line)
{
	
	int i=0, count=0;vector<string> line1;
			while(i<line.size())
			{
				
				if(line[i]=="*")
				{
					count=i;
					break;
				}
				line1.push_back(line[i]);
				i++;
			}
			if(count!=0)
			{				
				if(atomic_expr(line1))
				{
					if(line[count]=="*")
					{
						line.erase(line.begin(),line.begin()+count+1);
						if(atomic_expr(line))
						{
							PROD();
							return true;
						}
						else
						{
						// atomic_expr is wrong
						}
					}
					else
					{
					//* symbol missing
					}
				}
				else
				{
				// atomic_expr is wrong
				}
			}
		}			
//-----------------------------------------------------------------------------------------------------------------------------------
bool integer(string name, int count);
bool type(string line);
bool typed_attribute_list(vector<string> line, int count);
bool delete_cmd(vector<string> line);
bool update_cmd(vector<string> line);
bool insert_cmd(vector<string> line);
bool create_cmd(vector<string> line);
bool show_cmd(vector<string> line);
bool exit_cmd(vector<string> line);
bool write_cmd(vector<string> line);
bool close_cmd(vector<string> line);
bool open_cmd(vector<string> line);

bool command(vector<string> line)
{
	if(open_cmd(line) || close_cmd(line) || write_cmd(line) || exit_cmd(line) || show_cmd(line) || create_cmd(line) /*|| update_cmd() || insert_cmd() || delete_cmd() */)
	{
		return true;
	}
	return false;
}

//-------- open_cmd -------------
bool open_cmd(vector<string> line)
{
	if(line[0] == "open" || line[0] == "OPEN")
	{
		if(relation_name(line[1]))
		{
			return true;
		}
		else
		{
			//wrong relation name
		}
	}
	return false;
}
//-------- clse_cmd -------------
bool close_cmd(vector<string> line)
{
	if(line[0] == "CLOSE")
	{
		if(relation_name(line[1]))
		{
			return true;
		}
		else
		{
			//wrong relation name
		}
	}
}	
//-------- write_cmd -------------
bool write_cmd(vector<string> line)
{
	if(line[0] == "WRITE")
	{
		if(relation_name(line[1]))
			{
				return true;
			}
		else
			{
				//wrong relation name
			}
	}
}
//-------- exit_cmd -------------
bool exit_cmd(vector<string> line)
{
	if(line[0] == "EXIT")
	{
		return true;
	}
	else
	{
		//can't exit
	}
}
////-------- show_cmd -------------
bool show_cmd(vector<string> line)
{
	if(line[0] == "SHOW")
	{
		line.erase(line.begin(), line.begin()+2);
		if(atomic_expr(line))
		{
			return true;
		}
		else
		{
			//wrong relation name
		}
	}
}
//-------- create_cmd -------------

bool create_cmd(vector<string> line)
{
int i = 0;
int count = 0;
	if(line[0] == "CREATE")
	{
		if(line[1] == "TABLE" || line[1] == "table")
		{
			if(relation_name(line[2]) && line[3] == "(")
			{
				line.erase(line.begin(), line.begin()+4);
				while(i < line.size())
				{
					if(line[i]==")")
					{
						count=i;
						break;
					}
					i++;
				}
				if(count == 0)
				{
					//no table
				}
				if(typed_attribute_list(line,count-1))
				{
					line.erase(line.begin(), line.begin()+count);
					if(line[0] == "PRIMARY" || line[0] == "primary")
					{
						if(line[1] == "key" && line[2] == "(" || line[1] == "KEY" && line[2] == "(" )
						{
							line.erase(line.begin(), line.begin()+3);
							i=0;
							while(i < line.size())
							{
								if(line[i]==")")
								{
									count=i;
									break;
								}
								i++;
							}
							if(count == 0)
							{
								//no table
							}
							if(attribute_list(line,count-1))
							{
								return true;
							}
							else
							{
								//error attribute_lise
							}
							
						}
						else
						{
							//no key
						}
					}
					else
					{
						//no primary
					}
					
				}
				else
				{
					//wrong attribute list
				}
			
			}
			else
			{
				//wrong relation name, and no quotation
			}
		}
		else
		{
			//wrong table
		}
	}
}

//-------- update_cmd -------------

bool update_cmd(vector<string> line)
{
int i = 3;
int count = 0;
	if(line[0] == "UPDATE")
	{
		if(relation_name(line[1]))
		{
			if(line[2] == "set" || line[2] == "SET")
			{
				line.erase(line.begin(), (line.begin()+3));
				while(i < line.size())
				{
					//cheack for a literal relation_name or an =
					if(relation_name(line[i]) && line[i+1] == "=" && literal(line[i+2]) )
					{
						i=i+3;
					}
					else
					{
						count = i;
						break;
					}
				}
				if(count == 0)
				{
					//something is wrong or no table for update
				}
				if(line[count+1] == "where" ||line[count+1] == "WHERE" )
				{
					line.erase(line.begin(), line.begin()+count+2);
					if(conjunction(line,line.size()))
					{
						return true;
					}
					else
					{
						//something wrong with the condition
					}
				}
				else
				{
					//no where string
				}
			}
			else
			{
			}
		}
		else
		{
		}
	}
}

//-------- insert_cmd -------------

bool insert_cmd(vector<string> line)
{
//INSERT INTO relation-name VALUES FROM
int i = 0;
int count = 0;
	if(line[0] == "INSERT")
	{
		if(line[1] == "into" || line[1] == "INTO")
		{
			if(relation_name(line[2]))
			{
				if(line[3] == "VALUES" || line[3] == "values")
				{
					if(line[4] == "from" || line[4] == "FROM")
					{
						if(line[5] == "RELATION" || line[5] == "relation" || line[5] == "(") 
						{
							if(line[5] == "(")
							{
								line.erase(line.begin(), line.begin()+6);
								while(i < line.size())
								{
									if(line[i]==")")
									{
										count=i;
										break;
									}
									i++;
								}
								if(count == 0)
								{
									//no table
								}
								for(i = 0; i < count - 1; i++)
								{
									if(!literal(line[i]))
									{
										//something wrong with literals
									}
								}
								return true;
							}
							else
							{
								line.erase(line.begin(), line.begin()+6);
								if(expr(line))
								{
									return true;
								}
								else
								{
									//something wrong with expression
								}
							}
						}
						else
						{
							//no relation or (
						}
					}
					else
					{
					}
				}
				else
				{
				}
			}
			else
			{
				//wrong relation name
			}
		}
		else
		{
			//wrong into
		}
		
	}
}

//-------- delte_cmd -------------

bool delete_cmd(vector<string> line)
{
//DELETE FROM relation-name WHERE condition
	if(line[0] == "DELETE")
	{
		if(line[1] == "FROM" || line[1] == "from")
		{
			if(relation_name(line[2]))
			{
				if(line[3] == "WHERE" || line[3] == "where")
				{
					line.erase(line.begin(), line.begin()+4);
					if(conjunction(line,line.size()))
					{
						return true;
					}
					else
					{
						//wrong condition
					}
				}
				else
				{
					//wrong string
				}
			}
			else
			{
				//wrong relation name
			}
		}
		else
		{
		
			//wrong string
		}
	}
	else
	{
		//wrong string
	}
}


//-------- type_attribute_list -------------

bool typed_attribute_list(vector<string> line, int count)
{
	for(int i = 0; i < count; i= i + 2)
	{
		if(!relation_name(line[i]) && !type(line[i+1]))
		{
			return false;
		}
	}	
}

//-------- type -------------

bool type(string line)
{
	string variance_character = "VARCHARvarchar";
	int i = 0;
	int count;
	if(line == "integer" || line == "INTEGER")
	{
		return true;
	}
	while(i < 7)
	{
		if(variance_character[i] != line[i] && variance_character[i+7] != line[i])
		{
			//error varchar is spelled wrong
			return false;
		}
	}
	if(line[7] == '(')
	line.erase(line.begin(), line.begin()+8);
	i=0;
	while(line[i] < line.size())
	{
		if(line[i]==')')
		{
			count=i;
			break;
		}
		i++;
	}
	if(count == 0)
	{
		//no table
	}
	if(integer(line, count))
	{
		return true;
	}
	else
	{
		// no integer
	}
	
}

//-------- integer -------------

bool integer(string name, int count)
{
	for(int i = 0; i < count; i++)
	{	
		if(!isdigit(name[i]))
		{
			return false;
		}
	}
	return true;
}










void program(vector<string>& input)
{

		/***********************************************
		 For testing purposes this will output whats in
		 the vector "lines"
		************************************************/
		for(int i=0; i<input.size(); i++)
		{
			cout << "input[" << i << "] = " << input[i] << endl;
		}



	/*if(command(input))
	{
		cout << "COMMAND WORKED" << endl;
	}
	else */if(query(input))
	{
		cout << "QUERY WORKED" << endl;
	}
	else
	{
		cout << "DIDN'T WORK" << endl;
	}
}